Dev/backport mcp entity level config#3251
Open
anushakolan wants to merge 3 commits intorelease/1.7from
Open
Conversation
This change allows entity-level MCP configuration to control which entities participate in MCP runtime tools, providing granular control over DML operations and custom tool exposure. - Closes on #2948 This change introduces an optional mcp property at the entity level that controls participation in MCP's runtime tools. This is a prerequisite for custom tools support. The MCP property supports two formats: - **Boolean shorthand**: `"mcp": true` or `"mcp": false` - **Object format**: `{"dml-tools": boolean, "custom-tool": boolean}` Property Behavior: 1. Boolean Shorthand (`"mcp": true/false`) - `"mcp": true`: Enables DML tools only; custom tools remain disabled. - `"mcp": false`: Disables all MCP functionality for the entity. 2. Object Format `("mcp": { ... })` - `{ "dml-tools": true, "custom-tool": true }`: Enables both (valid only for stored procedures). - `{ "dml-tools": true, "custom-tool": false }`: DML only. - `{ "dml-tools": false, "custom-tool": true }`: Custom tool only (stored procedures). - `{ "dml-tools": false, "custom-tool": false }`: Fully disabled. Single-property cases: - `{"dml-tools": true}`: Enables DML only; auto-serializes to `"mcp": true`. - `{"custom-tool": true}`: Enables custom tool only; serializes as given. 3. No MCP Configuration in Entity (default) - `dml-tools` will still be enabled by default and no other change is behavior - [x] Unit Tests - [x] Integrations Tests - [x] CLI Command Testing Sample CLI commands: Add table with DML tools enabled `dab add Book --source books --permissions "anonymous:*" --mcp.dml-tools true` Add stored procedure with custom tool enabled `dab add GetBookById --source dbo.get_book_by_id --source.type stored-procedure --permissions "anonymous:execute" --mcp.custom-tool true` Add stored procedure with both properties `dab add UpdateBook --source dbo.update_book --source.type stored-procedure --permissions "anonymous:execute" --mcp.custom-tool true --mcp.dml-tools false`
- Closes on #3017 The entity-level MCP configuration (`Entity.Mcp.DmlToolEnabled` or `Entity.Mcp.CustomToolEnabled`) can override runtime-level settings. `DmlToolEnabled` defaults to true when unspecified, while `CustomToolEnabled` defaults to false. However, this entity-level configuration was not being checked by the MCP tools when they execute. The tools only checked the runtime-level configuration (e.g. `RuntimeConfig.McpDmlTools.ReadRecords`, etc.). This change addresses this gap for both built-in/DML tools and custom tools by adding entity-level validation before tool execution. - Added entity-level configuration checks to all 6 MCP tools (5 DML tools + 1 custom tool) that validate entity-specific flags before executing operations - DML tools (read_records, create_record, update_record, delete_record, execute_entity) now check `entity.Mcp.DmlToolEnabled` and return a `ToolDisabled` error when disabled at the entity level. - DynamicCustomTool checks `entity.Mcp.CustomToolEnabled` and return a `ToolDisabled` error - Tests covering various scenarios - [ ] Integration Tests - [x] Unit Tests Not applicable since it's a config level change and have been tested based on config settings. --------- Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
… same. (#3196) ## Why make this change? Closes #3194 - MCP `create_record` tool incorrectly blocks views with error `"The create_record tool is only available for tables."` 1. Views are the required workaround for unsupported SQL data types (e.g., vector columns). Users could create views that omit unsupported columns and perform DML operations against those views. 2. This bug prevents INSERT operations via MCP on view entities, breaking a critical workflow for vector database scenarios. ## What is this change? 1. Modified `CreateRecordTool.cs` to allow both tables and views to pass source type validation 2. Changed `else` block (which caught views) to`else if (EntitySourceType.StoredProcedure)` so only stored procedures are blocked 3. Views now fall through to the mutation engine, which already supports INSERT on updateable views 4. Updated error message to `"The create_record tool is only available for tables and views."` 5. Added 8 unit tests validating all DML tools (CreateRecord, ReadRecords, UpdateRecord, DeleteRecord) work with both Table and View source types ## How was this tested? - [ ] Integration Tests - [X] Unit Tests 1. `DmlTool_AllowsTablesAndViews` - 8 DataRow test cases verifying no `InvalidCreateTarget` error for views 2. Existing REST integration tests `InsertOneInViewTest` already validate view INSERT via same mutation engine Manually tested via MCP Inspector, to verify `create_record` calls succeeds on a view. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
Contributor
Author
|
/azp run |
|
Azure Pipelines successfully started running 6 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
Backports MCP entity-level configuration support into release/1.7, adds CLI/schema support for the new entities.<name>.mcp settings, and fixes MCP DML tooling behavior so create_record supports view-backed entities (plus associated tests).
Changes:
- Add entity-level MCP config model + JSON (de)serialization support and expose it through CLI add/update flags.
- Enforce entity-level enablement checks in MCP tools (DML + custom tools), and allow
create_recordfor view entities. - Add/extend unit tests and JSON schema updates covering entity-level MCP config and tool behavior.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Service.Tests/ModuleInitializer.cs | Updates snapshot verification settings to ignore new MCP user-provided flags. |
| src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs | Adds MCP tool execution tests for entity-level enablement and view/table support. |
| src/Service.Tests/Configuration/EntityMcpConfigurationTests.cs | Adds config deserialization/validation tests for entity-level mcp formats. |
| src/Config/RuntimeConfigLoader.cs | Registers the new entity-level MCP converter for config JSON parsing/serialization. |
| src/Config/ObjectModel/EntityMcpOptions.cs | Introduces the entity-level MCP options model and user-provided flags. |
| src/Config/ObjectModel/Entity.cs | Adds Entity.Mcp to the object model and wires converter usage. |
| src/Config/Converters/EntityMcpOptionsConverterFactory.cs | Implements boolean/object JSON forms for entities.<name>.mcp. |
| src/Cli/Utils.cs | Adds CLI parsing/validation helper for MCP entity options. |
| src/Cli/ConfigGenerator.cs | Plumbs MCP options through dab add/dab update entity generation. |
| src/Cli/Commands/UpdateOptions.cs | Adds MCP CLI parameters to update options plumbing. |
| src/Cli/Commands/EntityOptions.cs | Adds --mcp.dml-tools and --mcp.custom-tool options. |
| src/Cli/Commands/AddOptions.cs | Adds MCP CLI parameters to add options plumbing. |
| src/Cli.Tests/UpdateEntityTests.cs | Adds CLI update tests covering MCP entity option behavior/validation. |
| src/Cli.Tests/ModuleInitializer.cs | Updates snapshot verification settings to ignore new MCP user-provided flags. |
| src/Cli.Tests/AddEntityTests.cs | Adds CLI add tests covering MCP entity option behavior/validation. |
| src/Azure.DataApiBuilder.Mcp/Utils/McpErrorHelpers.cs | Extends ToolDisabled helper to optionally use a custom message. |
| src/Azure.DataApiBuilder.Mcp/Core/DynamicCustomTool.cs | Adds runtime entity-level enablement validation for custom tools (hot-reload scenario). |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/UpdateRecordTool.cs | Adds entity-level DML enablement checks + validates table/view targets. |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/ReadRecordsTool.cs | Adds entity-level DML enablement checks + validates table/view targets. |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/ExecuteEntityTool.cs | Adds entity-level DML enablement check and hardens null entity map handling. |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/DeleteRecordTool.cs | Adds entity-level DML enablement checks. |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/CreateRecordTool.cs | Allows view targets (skips table-only validation) + adds entity-level DML checks. |
| schemas/dab.draft.schema.json | Documents/defines entity-level mcp schema and adds stored-proc constraint for custom tools. |
Comment on lines
+1175
to
+1186
| "if": { | ||
| "properties": { | ||
| "mcp": { | ||
| "properties": { | ||
| "custom-tool": { | ||
| "const": true | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "required": ["mcp"] | ||
| }, |
Comment on lines
+88
to
+121
| public override void Write(Utf8JsonWriter writer, EntityMcpOptions value, JsonSerializerOptions options) | ||
| { | ||
| if (value == null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // Check if we should write as boolean shorthand | ||
| // Write as boolean if: only dml-tools is set (or custom-tool is default false) | ||
| bool writeAsBoolean = !value.UserProvidedCustomToolEnabled && value.UserProvidedDmlToolsEnabled; | ||
|
|
||
| if (writeAsBoolean) | ||
| { | ||
| // Write as boolean shorthand | ||
| writer.WriteBooleanValue(value.DmlToolEnabled); | ||
| } | ||
| else if (value.UserProvidedCustomToolEnabled || value.UserProvidedDmlToolsEnabled) | ||
| { | ||
| // Write as object | ||
| writer.WriteStartObject(); | ||
|
|
||
| if (value.UserProvidedCustomToolEnabled) | ||
| { | ||
| writer.WriteBoolean("custom-tool", value.CustomToolEnabled); | ||
| } | ||
|
|
||
| if (value.UserProvidedDmlToolsEnabled) | ||
| { | ||
| writer.WriteBoolean("dml-tools", value.DmlToolEnabled); | ||
| } | ||
|
|
||
| writer.WriteEndObject(); | ||
| } | ||
| } |
Comment on lines
+1670
to
+1671
| // Keep existing MCP options if no updates provided | ||
| updatedMcpOptions = entity.Mcp; |
| // Assert | ||
| Assert.IsTrue(result.IsError == true, "Expected error when entity has DmlToolEnabled=false"); | ||
|
|
||
| JsonElement content = await RunToolAsync(tool, arguments, serviceProvider); |
| CancellationToken cancellationToken = default) | ||
| { | ||
| ILogger<DynamicCustomTool>? logger = serviceProvider.GetService<ILogger<DynamicCustomTool>>(); | ||
| string toolName = GetToolMetadata().Name; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why make this change?
This backport fixes MCP behavior where create_record incorrectly rejected view-backed entities with the error that the tool is only available for tables.
Views are a required workaround for unsupported SQL data types in some scenarios (e.g., vector columns), so this fix restores expected INSERT behavior for those entities.
Note: This backport includes prerequisite PRs #2989 and #3084 which were not previously in release/1.7 but are required for the test infrastructure.
What is this change?
Cherry-picked PR:
How was this tested?
create_recordagainst view-backed entities.Sample Request(s)
N/A